package task

import (
	"context"
	chatdialogservicelogic "paper-pro/app/chat/rpc/internal/logic/chatdialogservice"
	"paper-pro/app/chat/rpc/internal/svc"
	"paper-pro/app/chat/rpc/pb"
	delchattask "paper-pro/pkg/types"
	"paper-pro/pkg/xerr"
	"sync"
	"time"

	"github.com/zeromicro/go-queue/dq"
	"github.com/zeromicro/go-zero/core/logx"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
)

type DeleteTask struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
	dqConsumer dq.Consumer
}

func NewDeleteTask(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteTask {
	return &DeleteTask{
		ctx:        ctx,
		svcCtx:     svcCtx,
		Logger:     logx.WithContext(ctx),
		dqConsumer: dq.NewConsumer(svcCtx.Config.DqConsumerConf),
	}
}

func (t *DeleteTask) StartGo(wg *sync.WaitGroup) {
	go func() {
		if wg != nil {
			wg.Add(1)
			defer wg.Done()
		}
		t.dqConsumer.Consume(t.handleDelete)
		t.Info("DeleteTask fnish bye~bye~")
	}()
}

func (t *DeleteTask) handleDelete(payload []byte) {
	delTask, err := delchattask.UnmarshalDelTask(payload)
	if err != nil {
		t.Errorf("Chat DeleteTask: handleDelete UnmarshalDelTask payload: %s, error: %v", payload, err)
		return
	}
	ctx, cancel := context.WithTimeout(t.ctx, 10*time.Second)
	defer cancel()
	switch delTask.DelType {
	case delchattask.DelayDelDialogByAssistant:
		t.delDialogByAssistant(ctx, delTask.Data)
	case delchattask.DelayDelMsgByAssistant:
		t.delMsgByDialogs(ctx, delTask.Data)
	case delchattask.DelayDelMsgByDialog:
		t.delMsgByDialog(ctx, delTask.Data)
	}
}

func (t *DeleteTask) delDialogByAssistant(ctx context.Context, data []byte) {
	req, err := delchattask.UnmarshalDelAssistantInfo(data)
	if err != nil {
		t.Errorf("Chat DeleteTask: DelDialogByAssistant UnmarshalDelAssistantInfo data: %s, error: %v", data, err)
		return
	}
	delLogic := chatdialogservicelogic.NewDeleteManyLogic(ctx, t.svcCtx)
	_, err = delLogic.DeleteMany(&pb.ChatDialogDeleteManyReq{
		AssistantId: req.AssistantId,
		UserId:      req.UserId,
	})
	if err != nil {
		t.Errorf("Chat DeleteTask: DelDialogByAssistant ID: %s DeleteMany error: %v", req.AssistantId, err)
	}
}

func (t *DeleteTask) delMsgByDialogs(ctx context.Context, data []byte) {
	req, err := delchattask.UnmarshalDelDialogsInfo(data)
	if err != nil {
		t.Errorf("Chat DeleteTask: delMsgByDialogs UnmarshalDelDialogsInfo data: %s, error: %v", data, err)
		return
	}

	dialogIds := make([]*primitive.ObjectID, 0, len(req.DialogIds))
	for _, id := range req.DialogIds {
		oID, err := primitive.ObjectIDFromHex(id)
		if err != nil {
			t.Errorf("Chat DeleteTask: delMsgByDialogs ObjectIDFromHex id: %s error: %v", id, err)
			continue
		}
		dialogIds = append(dialogIds, &oID)
	}
	if len(dialogIds) == 0 {
		t.Errorf("Chat DeleteTask: delMsgByDialogs UnmarshalDelDialogsInfo data: %s, error: %v",
			data, xerr.NewErrCode(xerr.DB_UPDATE_AFFECTED_ZERO_ERROR))
		return
	}

	_, err = t.svcCtx.ChatMsgModel.DeleteMany(ctx, bson.M{"dialogId": bson.M{"$in": dialogIds}, "userId": req.UserId})
	if err != nil {
		t.Errorf("Chat DeleteTask: delMsgByDialogs DB DeleteMany error: %v", err)
	}
}

func (t *DeleteTask) delMsgByDialog(ctx context.Context, data []byte) {
	req, err := delchattask.UnmarshalDelOneDialogInfo(data)
	if err != nil {
		t.Errorf("Chat DeleteTask: delMsgByDialog UnmarshalDelOneDialogInfo data: %s, error: %v", data, err)
		return
	}

	oID, err := primitive.ObjectIDFromHex(req.DialogId)
	if err != nil {
		t.Errorf("Chat DeleteTask: delMsgByDialog ObjectIDFromHex id: %s error: %v", req.DialogId, err)
		return
	}

	_, err = t.svcCtx.ChatMsgModel.DeleteMany(ctx, bson.M{"dialogId": oID, "userId": req.UserId})
	if err != nil {
		t.Errorf("Chat DeleteTask: delMsgByDialog ID: %s DB DeleteMany error: %v", req.DialogId, err)
	}
}
